package com.ruoyi.common.utils;

import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;

/**
 * base26Utils
 *
 * @author liliangyu
 */
@Slf4j
public class SuperShortCodeUtils {

    /**
     * 序号转字符串
     * 年月日0000001->年月日9999999
     * 需要严格控制处理后的长度 要求一致
     * 前6位 YYMMDD
     * 后7位 0000001-9999999
     *
     * @param no
     * @return
     */
    public static String noToStr(final String no) {
        log.info("原始序号:{}", no);
        final String oddStr = no.replaceAll("(.)(.)", "$1");
        final String evenStr = no.replaceAll("(.)(.)", "$2");
        final long checkNum2 = calculateCheckNum(oddStr, evenStr);
        // 原始序号+校验位
        final String newStr = no + checkNum2;
        log.info("原始序号+校验位:{}", newStr);
        // 使用大写字母base62编码
        return Base36Utils.encode(Long.parseLong(newStr));
    }

    /**
     * 字符串转序号
     *
     * @param str
     * @return
     */
    public static String strToNo(final String str) {
//        log.info("加密后:{}", str);
        final String newStr = String.valueOf(Base36Utils.decode(str));
//        log.info("解密后:{}", newStr);
        //取最后一位
        final String last = StrUtil.sub(newStr, newStr.length() - 1, newStr.length());
        final long lastLong = Long.parseLong(last);
        // 移除最后一位
        final String newStr2 = StrUtil.sub(newStr, 0, newStr.length() - 1);
        //
        final String oddStr = newStr2.replaceAll("(.)(.)", "$1");
        final String evenStr = newStr2.replaceAll("(.)(.)", "$2");
        final long checkNum2 = calculateCheckNum(oddStr, evenStr);

        if (checkNum2 != lastLong) {
            log.error("验证失败:{}", str);
            throw new ServiceException("验证失败");
        }
        return newStr2;
    }

    /**
     * 奇数位+(偶数位*3)     取10的模
     *
     * @param oddStr
     * @param evenStr
     * @return
     */
    private static long calculateCheckNum(final String oddStr, final String evenStr) {
        final long oddLong = Long.parseLong(oddStr);
        final long evenLong = Long.parseLong(evenStr);
        final long check = oddLong + evenLong * 3;
        // %10
        return check % 10;
    }


}
